/*
 * trdp_mini.c
 *
 *  Created on: 2016骞�12鏈�7鏃�
 *      Author: ZhangYu @ DL-LaiKe
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <unistd.h>
#include	"../api/trdp_mini.h"
#include	"../inc/trdp_mini_private.h"
#include	"../inc/trdp_mini_proto.h"
#include	"../inc/trdp_mini_vos.h"
#include	"../inc/msgQ.h"

#define			TRDP_MINI_AUHENTICATION_FILE	"/usr/share/applications/msg.sq"
#define			UP_TIME_FILE	"/proc/uptime"
/***********************************************************************************************************************
 *  LOCALS
 */
BOOLEAN     sIsBigEndian;
INT32U		gMsTimerCnt;											/* every time user call process TRDP Stack the variable increase one step*/
static MEM_CTRL_T	gMem;														/* global memory block variable */
static void 	*sendPdMsgs[TRDP_MINI_PD_Q_LEN], *sendMdMsgs[TRDP_MINI_MD_Q_LEN];	/* send message lists for message queue */
static void 	*pSendPdMsg, *pSendMdMsg;											/*Message Queue elements for send message*/
static PD_INFO_T	pdInfo[TRDP_MINI_PD_CTRL_MAX_NUM];							/* PD send or receive message control block*/
static MD_INFO_T	mdInfo[TRDP_MINI_MD_CTRL_MAX_NUM];							/* MD send or receive message control block*/
static INT8U		udpData[1460];												/* UDP Data Buffer to hold send data */
static INT8U		tcpData[1460];												/* TCP Data Buffer to hold send data */

INT32U		mdSeqID = 0;

/***********************************************************************************************************************
 *  LOCALS function declare
 */
static INT32U checkPdComId(INT32U comId, INT8U *pDestIP);
static PD_INFO_T* findNewPdEle(void);
static INT8U waitMsTicks(INT32U startCnt, INT32U ticks);
static void receive_pd_callBack(void *arg, INT8U *pData, INT32U dataSize, INT8U *pRecvIp, INT16U recvPort);
static void receive_md_callBack(void *arg, INT8U *pData, INT32U dataSize, INT8U *pRecvIp, INT16U recvPort);
static int checkAuthentication(void);
static int getTick(struct timeval *time);
static int changeForm(char *fileTime, struct timeval *time);
/***********************************************************************************************************************
 * GLOBAL FUNCTIONS
 */

/*********************************************************************
 * NAME			: getTick
 * FUNCTION		: get Ms time from linux updateFile
 * OUTPUT		: int	*time	: time struct
 * RETURN		: OK			:
 * 				: ERROR			:
 ********************************************************************/
static int getTick(struct timeval *time)
{
	char fileTime[32];
	int fd = 0;
	int i;

	memset(fileTime, 0, sizeof(fileTime));

	if((fd = open(UP_TIME_FILE, O_RDONLY)) >= 0){
		if(read(fd, fileTime, sizeof(fileTime) - 1) >= 0){
			for(i=0; i < sizeof(fileTime); i++){
				if(fileTime[i] == ' '){
					fileTime[i] = 0;
					break;
				}
			}
			changeForm(fileTime, time);
		}
		close(fd);
	}

	return OK;
}

/*********************************************************************
 * NAME			: changeForm
 * FUNCTION		: change the time formate
 * INPUT		: char	*fileTime	: linux update file
 * OUTPUT		: int	*time		: time struct
 * RETURN		: OK				: excute OK
 ********************************************************************/
static int changeForm(char *fileTime, struct timeval *time)
{
	char	buf[32];
	char	*p;

	unsigned int	hl=0, ll=0, hlen=0;

	memset(buf,0,sizeof(buf));

	p = strstr(fileTime, ".");
	hlen = p - fileTime;
	strncpy(buf, fileTime, hlen);

	hl = atol(buf);
//	hl = hl*100;
	p++;

	if(strlen(p) == 1){
		ll = atol(p)*100;
	}else if(strlen(p) == 2){
		ll = atol(p)*10;
	}
	time -> tv_sec = (int)hl;
	time -> tv_usec = (int)ll * 1000;
	return OK;
}


double trdp_mini_getTick(void)
{
	struct timeval	nowTime;
	memset(&nowTime, 0, sizeof(nowTime));

	getTick(&nowTime);

	return ((double)(nowTime.tv_sec) + ((double)nowTime.tv_usec/1000000));
}

static int checkAuthentication(void)
{
	char authentication[32];
	int fd = 0;

	memset(authentication, 0, sizeof(authentication));

	if((fd = open(TRDP_MINI_AUHENTICATION_FILE, O_RDONLY)) < 0){
		return ERROR;
	}

	if(read(fd, authentication, sizeof(authentication) - 1) < 0){
		close(fd);
		return ERROR;
	}
	close(fd);

	if(strcmp(authentication, "readmeforaccbv1.0") == 0){
		return OK;
	}
	return ERROR;
}



/**********************************************************************************************************************/
/** Initialize the TRDP MINI stack for SO lib.
 * */
TRDP_MINI_ERR_T trdp_mini_init_so(INT8U ifCnt, INT8U mcCnt, const char * ifAddress[],  const char * mcAddress[], INT8U qos, INT8U ttl, COM_TYPE_T comType)
{
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	// if(checkAuthentication() == ERROR){
	// 	printf("###ERROR: check authentication failed!\n");
	// 	return TRDP_MINI_NOINIT_ERR;
	// }

	if(trdp_mini_init() != TRDP_MINI_NO_ERR){
		return TRDP_MINI_INIT_ERR;
	}

	if(vois_init_unicast_socket(2, ttl) == ERROR){
		ret = TRDP_MINI_INIT_ERR;
	}

	if(vois_init_multicast_socket(ifCnt, mcCnt, ifAddress, mcAddress, qos, ttl) == ERROR){
		ret = TRDP_MINI_INIT_ERR;
	}

	if(ret == TRDP_MINI_NO_ERR){
		if(vos_init_recv_thread() == ERROR){
			ret = TRDP_MINI_INIT_ERR;
		}
	}

	return ret;
}

TRDP_MINI_ERR_T trdp_mini_delay(INT32U delay)
{
	if(delay > 150) delay -= 150;

	if(vos_threadDelay(delay) == OK){
		return TRDP_MINI_NO_ERR;
	}

	return TRDP_MINI_TIMEOUT_ERR;
}

/**********************************************************************************************************************/
/** Initialize the TRDP MINI stack.
 * */
TRDP_MINI_ERR_T	trdp_mini_init(void)
{
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	/*  Compute endianess  */
	long        one = 1;
	sIsBigEndian = !(*((char *)(&one)));

	/* initialize global variables */
	memset(&gMem, 0, sizeof(gMem));
	memset(pdInfo, 0, sizeof(pdInfo));
	memset(mdInfo, 0, sizeof(mdInfo));

	/* initialize send Message Queue */
	OS_QInit();
	pSendPdMsg = OSQCreate(sendPdMsgs,TRDP_MINI_PD_Q_LEN);
	pSendMdMsg = OSQCreate(sendMdMsgs,TRDP_MINI_MD_Q_LEN);

	if((pSendPdMsg == NULL) && (TRDP_MINI_PD_Q_LEN > 0)){
		ret = TRDP_MINI_INIT_ERR;
	}

	if((pSendMdMsg == NULL) && (TRDP_MINI_MD_Q_LEN > 0)){
			ret = TRDP_MINI_INIT_ERR;
		}

	return ret;
}

/**********************************************************************************************************************/
/** prepare process data by comID
 * */
TRDP_MINI_ERR_T trdp_mini_pd_prepare(INT32U comId, INT8U *pData, INT32U dataSize, INT8U *pSrcIP, INT8U *pDestIP, INT32U etbTopoCnt, INT32U interval, COM_TYPE_T comType)
{
	int i = 0, m = 0, b = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;
	INT32U  blockSize[TRDP_MINI_NBK_SIZES] = TRDP_MINI_MEM_BLKSIZE;


	if((pData == NULL) || (pSrcIP == NULL) || (pDestIP == NULL) || (interval == 0)){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){
		/*find if there is already one comId block has been set yet*/
		if(checkPdComId(comId, pDestIP) == OK){
			/*comId Check OK, so we prepare one new comId*/
			for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
				if((pdInfo[i].flagBits & FLAGS_ENABLE) == 0){
					/* prepare the memory block for the update data*/
					for(m = 0; m < TRDP_MINI_NBK_SIZES; m++){
						if(blockSize[m] >=  dataSize){
							/*find one block class can hold the data*/
							switch(blockSize[m]){
#if TRDP_MINI_BLKCNT_16B > 0
							case 16:
								for(b=0; b<TRDP_MINI_BLKCNT_16B; b++){
									if(gMem.mb16B[b].isValid == 0){
                                        gMem.mb16B[b].isValid = 1;
										memcpy(gMem.mb16B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb16B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
							case 32:
								for(b=0; b<TRDP_MINI_BLKCNT_32B; b++){
									if(gMem.mb32B[b].isValid == 0){
                                        gMem.mb32B[b].isValid = 1;
										memcpy(gMem.mb32B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb32B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
							case 64:
								for(b=0; b<TRDP_MINI_BLKCNT_64B; b++){
									if(gMem.mb64B[b].isValid == 0){
                                        gMem.mb64B[b].isValid = 1;
										memcpy(gMem.mb64B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb64B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
							case 128:
								for(b=0; b<TRDP_MINI_BLKCNT_128B; b++){
									if(gMem.mb128B[b].isValid == 0){
                                        gMem.mb128B[b].isValid = 1;
										memcpy(gMem.mb128B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb128B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
							case 256:
								for(b=0; b<TRDP_MINI_BLKCNT_256B; b++){
									if(gMem.mb256B[b].isValid == 0){
                                        gMem.mb256B[b].isValid = 1;
										memcpy(gMem.mb256B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb256B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
							case 512:
								for(b=0; b<TRDP_MINI_BLKCNT_512B; b++){
									if(gMem.mb512B[b].isValid == 0){
                                        gMem.mb512B[b].isValid = 1;
										memcpy(gMem.mb512B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb512B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
							case 1024:
								for(b=0; b<TRDP_MINI_BLKCNT_1024B; b++){
									if(gMem.mb1024B[b].isValid == 0){
                                        gMem.mb1024B[b].isValid = 1;
										memcpy(gMem.mb1024B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb1024B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
							case 1348:
								for(b=0; b<TRDP_MINI_BLKCNT_1348B; b++){
									if(gMem.mb1348B[b].isValid == 0){
                                        gMem.mb1348B[b].isValid = 1;
										memcpy(gMem.mb1348B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb1348B[b];
										break;
									}
								}
								break;
#endif
							default:
								break;
							}
							if(pdInfo[i].pMemory != NULL){
								pdInfo[i].blockSize = blockSize[m];
								/*we find one unused PD control block*/
								pdInfo[i].flagBits |= FLAGS_ENABLE|FLAGS_AUTO;			//active this PD control block
								pdInfo[i].comId = comId;								//initialize the PD info
								pdInfo[i].dataSize = dataSize;							//initialize the datasize
								memcpy(pdInfo[i].srcIpAddr, pSrcIP, sizeof(pdInfo[i].srcIpAddr));
								memcpy(pdInfo[i].destIpAddr, pDestIP, sizeof(pdInfo[i].destIpAddr));
								pdInfo[i].etbTopoCnt = etbTopoCnt;
								pdInfo[i].interval = interval;
								pdInfo[i].msgType = TRDP_MINI_MSG_PD;
								pdInfo[i].comType = comType;
								pdInfo[i].lastTimerCnt = gMsTimerCnt;
								ret = TRDP_MINI_NO_ERR;
								//break out if we find one
								break;
							}
						}
					}
					//break out the find block loop
					break;
				}
			}
			if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
				//we can't find the control block
				ret = TRDP_MINI_MEM_ERR;
			}
		}else{
			ret = TRDP_MINI_PARAM_ERR;
		}
		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	return ret;
}


TRDP_MINI_ERR_T trdp_mini_pd_put(INT32U comId, INT8U *pData, INT32U dataSize, INT8U *pSrcIP, INT8U *pDestIP)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if(pData == NULL){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){
		for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
			if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == comId) && (memcmp(pdInfo[i].destIpAddr, pDestIP, 4) == 0)){
				//we find the specified control block
				if(dataSize <= pdInfo[i].blockSize){
					switch(pdInfo[i].blockSize){
#if TRDP_MINI_BLKCNT_16B > 0
					case 16:
						memcpy(((struct m16B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
					case 32:
						memcpy(((struct m32B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
					case 64:
						memcpy(((struct m64B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
					case 128:
						memcpy(((struct m128B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
					case 256:
						memcpy(((struct m256B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
					case 512:
						memcpy(((struct m512B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
					case 1024:
						memcpy(((struct m1024B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
					case 1348:
						memcpy(((struct m1348B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
					default:
						ret = TRDP_MINI_PARAM_ERR;
						break;
					}
				}else{
					ret = TRDP_MINI_PARAM_ERR;
				}

				pdInfo[i].lastTimerCnt = gMsTimerCnt;
				if(OSQPostOpt(pSendPdMsg, (void *)&pdInfo[i], OS_POST_OPT_NONE) != OK){
					if(pdInfo[i].pUserCbFunc != NULL){
						pdInfo[i].pUserCbFunc(NULL, pdInfo[i].comId, NULL, 0, NULL, TRDP_MINI_PD_UDP_PORT, TRDP_MINI_QUEUE_FULL_ERR);
					}
				}else{
					ret = TRDP_MINI_NO_ERR;
					trdp_mini_process();
				}

				//get out the loop
				break;
			}
			if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
				//we can't find the specified comId
				ret = TRDP_MINI_COMID_ERR;
			}
		}
		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	return ret;

}
/**********************************************************************************************************************/
/** update process data by comID
 * */
TRDP_MINI_ERR_T trdp_mini_pd_update(INT32U comId, INT8U *pData, INT32U dataSize, INT8U *pDestIP)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if(pData == NULL){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){
		for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
			if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == comId) && (memcmp(pdInfo[i].destIpAddr, pDestIP, 4) == 0)){
				//we find the specified control block
				if(dataSize <= pdInfo[i].blockSize){
					switch(pdInfo[i].blockSize){
#if TRDP_MINI_BLKCNT_16B > 0
					case 16:
						memcpy(((struct m16B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
					case 32:
						memcpy(((struct m32B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
					case 64:
						memcpy(((struct m64B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
					case 128:
						memcpy(((struct m128B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
					case 256:
						memcpy(((struct m256B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
					case 512:
						memcpy(((struct m512B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
					case 1024:
						memcpy(((struct m1024B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
					case 1348:
						memcpy(((struct m1348B_T *)pdInfo[i].pMemory)->data, pData, (int)dataSize);
						break;
#endif
					default:
						break;
					}
				}else{
					ret = TRDP_MINI_PARAM_ERR;
				}
				//get out the loop
				break;
			}
			if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
				//we can't find the specified comId
				ret = TRDP_MINI_COMID_ERR;
			}
		}

		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** unprepare process data by comID
 * */
TRDP_MINI_ERR_T trdp_mini_pd_unprepare(INT32U comId, INT8U *pDestIP)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if(comId == 0){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){

		for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
			if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == comId) && (memcmp(pdInfo[i].destIpAddr, pDestIP, 4) == 0)){
				switch(pdInfo[i].blockSize){
#if TRDP_MINI_BLKCNT_16B > 0
				case 16:
					((struct m16B_T *)pdInfo[i].pMemory)->isValid = 0;
					break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
				case 32:
					((struct m32B_T *)pdInfo[i].pMemory)->isValid = 0;
					break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
				case 64:
					((struct m64B_T *)pdInfo[i].pMemory)->isValid = 0;
					break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
				case 128:
					((struct m128B_T *)pdInfo[i].pMemory)->isValid = 0;
					break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
				case 256:
					((struct m256B_T *)pdInfo[i].pMemory)->isValid = 0;
					break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
				case 512:
					((struct m512B_T *)pdInfo[i].pMemory)->isValid = 0;
					break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
				case 1024:
					((struct m1024B_T *)pdInfo[i].pMemory)->isValid = 0;
					break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
				case 1348:
					((struct m1348B_T *)pdInfo[i].pMemory)->isValid = 0;
					break;
#endif
				default:
					break;
				}

				memset(&pdInfo[i], 0, sizeof(pdInfo[i]));
				break;
			}
		}
		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
		ret = TRDP_MINI_NOSESSION_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** activate redundancy port by comID
 * */
TRDP_MINI_ERR_T trdp_mini_pd_activateRed(void)
{
	gIsRedPortActive = 1;

	return TRDP_MINI_NO_ERR;
}

/**********************************************************************************************************************/
/** deactivate redundancy port by comID
 * */
TRDP_MINI_ERR_T trdp_mini_pd_deactivateRed(void)
{
	gIsRedPortActive = 0;

	return TRDP_MINI_NO_ERR;
}


TRDP_MINI_ERR_T trdp_mini_pd_chageSeqID(INT32U comId, INT32U seqID)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if(comId == 0){
		return TRDP_MINI_PARAM_ERR;
	}

	for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
		if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == comId)){
			pdInfo[i].seqCount = seqID;
		}
	}

	if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
		ret = TRDP_MINI_NOSESSION_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** request comId Data with auto flag
 * */
TRDP_MINI_ERR_T trdp_mini_pd_request(INT32U comId,  INT8U *pData, INT32U dataSize, INT8U *pSrcIP, INT8U *pDestIP, INT32U etbTopoCnt, INT32U timeOut, COM_TYPE_T comType, TRDP_MINI_PD_CALLBACK_T pUserCallBack)
{
	int i = 0, m = 0, b = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;
	INT32U  blockSize[TRDP_MINI_NBK_SIZES] = TRDP_MINI_MEM_BLKSIZE;

	if((pSrcIP == NULL) || (pDestIP == NULL) || (pUserCallBack == NULL)){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){
		for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
			if((pdInfo[i].flagBits & FLAGS_ENABLE) == 0){
				/* prepare the memory block for the update data*/
				if(dataSize > 0 && pData != NULL){
					for(m = 0; m < TRDP_MINI_NBK_SIZES; m++){
						if(blockSize[m] >=  dataSize){
							/*find one block class can hold the data*/
							switch(blockSize[m]){
#if TRDP_MINI_BLKCNT_16B > 0
							case 16:
								for(b=0; b<TRDP_MINI_BLKCNT_16B; b++){
									if(gMem.mb16B[b].isValid == 0){
                                        gMem.mb16B[b].isValid = 1;
										memcpy(gMem.mb16B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb16B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
							case 32:
								for(b=0; b<TRDP_MINI_BLKCNT_32B; b++){
									if(gMem.mb32B[b].isValid == 0){
                                        gMem.mb32B[b].isValid = 1;
										memcpy(gMem.mb32B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb32B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
							case 64:
								for(b=0; b<TRDP_MINI_BLKCNT_64B; b++){
									if(gMem.mb64B[b].isValid == 0){
                                        gMem.mb64B[b].isValid = 1;
										memcpy(gMem.mb64B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb64B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
							case 128:
								for(b=0; b<TRDP_MINI_BLKCNT_128B; b++){
									if(gMem.mb128B[b].isValid == 0){
                                        gMem.mb128B[b].isValid = 1;
										memcpy(gMem.mb128B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb128B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
							case 256:
								for(b=0; b<TRDP_MINI_BLKCNT_256B; b++){
									if(gMem.mb256B[b].isValid == 0){
                                        gMem.mb256B[b].isValid = 1;
										memcpy(gMem.mb256B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb256B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
							case 512:
								for(b=0; b<TRDP_MINI_BLKCNT_512B; b++){
									if(gMem.mb512B[b].isValid == 0){
                                        gMem.mb512B[b].isValid = 1;
										memcpy(gMem.mb512B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb512B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
							case 1024:
								for(b=0; b<TRDP_MINI_BLKCNT_1024B; b++){
									if(gMem.mb1024B[b].isValid == 0){
                                        gMem.mb1024B[b].isValid = 1;
										memcpy(gMem.mb1024B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb1024B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
							case 1348:
								for(b=0; b<TRDP_MINI_BLKCNT_1348B; b++){
									if(gMem.mb1348B[b].isValid == 0){
                                        gMem.mb1348B[b].isValid = 1;
										memcpy(gMem.mb1348B[b].data, pData, (int)dataSize);
										pdInfo[i].pMemory = (void *)&gMem.mb1348B[b];
										break;
									}
								}
								break;
#endif
							default:
								break;
							}
							if(pdInfo[i].pMemory != NULL){
								pdInfo[i].blockSize = blockSize[m];
								/*we find one unused PD control block*/
								pdInfo[i].flagBits |= FLAGS_ENABLE;						//active this PD control block
								pdInfo[i].comId = comId;								//initialize the PD info
								pdInfo[i].dataSize = dataSize;							//initialize the datasize
								memcpy(pdInfo[i].srcIpAddr, pSrcIP, sizeof(pdInfo[i].srcIpAddr));
								memcpy(pdInfo[i].destIpAddr, pDestIP, sizeof(pdInfo[i].destIpAddr));
								pdInfo[i].etbTopoCnt = etbTopoCnt;
								pdInfo[i].interval = timeOut;
								pdInfo[i].msgType = TRDP_MINI_MSG_PR;
								pdInfo[i].comType = comType;
								pdInfo[i].pUserCbFunc = pUserCallBack;
								if(OSQPostOpt(pSendPdMsg, (void *)&pdInfo[i], OS_POST_OPT_NONE) != OK){
									ret = TRDP_MINI_QUEUE_FULL_ERR;
								}else{
									ret = TRDP_MINI_NO_ERR;
									trdp_mini_process();
								}

								//break out if we find one
								break;
							}
						}
					}
				}else{
					/*we find a PD Control block to hold our request */
					pdInfo[i].flagBits |= FLAGS_ENABLE;						//active this PD control block
					pdInfo[i].comId = comId;								//initialize the PD info
					pdInfo[i].replyComId = comId;							//request replay comId

					memcpy(pdInfo[i].srcIpAddr, pSrcIP, sizeof(pdInfo[i].srcIpAddr));
					memcpy(pdInfo[i].destIpAddr, pDestIP, sizeof(pdInfo[i].destIpAddr));

					pdInfo[i].etbTopoCnt = etbTopoCnt;
					pdInfo[i].interval = timeOut;
					pdInfo[i].msgType = TRDP_MINI_MSG_PR;
					pdInfo[i].comType = comType;
					pdInfo[i].pUserCbFunc = pUserCallBack;

					if(OSQPostOpt(pSendPdMsg, (void *)&pdInfo[i], OS_POST_OPT_NONE) != OK){
						ret = TRDP_MINI_QUEUE_FULL_ERR;
					}else{
						trdp_mini_process();
					}
					break;
				}
				break;
			}
		}
		if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
			ret = TRDP_MINI_MEM_ERR;
		}
		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** subscribe one comId, get one communication block ready for receive the specified comId
 * */
TRDP_MINI_ERR_T trdp_mini_pd_subscribe(INT32U comId, INT8U *pSrcIP, INT8U *pDestIP, COM_TYPE_T comType, TRDP_MINI_PD_CALLBACK_T pUserCallBack)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if((pSrcIP == NULL) || (pDestIP == NULL) || (pUserCallBack == NULL)){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){
		for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
			if((pdInfo[i].flagBits & FLAGS_ENABLE) == 0){
				/*we find a PD Control block to hold our request */
				pdInfo[i].flagBits |= FLAGS_ENABLE|FLAGS_MODE;						//active this PD control block
				pdInfo[i].comId = comId;								//initialize the PD info

				memcpy(pdInfo[i].srcIpAddr, pSrcIP, sizeof(pdInfo[i].srcIpAddr));
				memcpy(pdInfo[i].destIpAddr, pDestIP, sizeof(pdInfo[i].destIpAddr));

				pdInfo[i].msgType = TRDP_MINI_MSG_PD;
				pdInfo[i].comType = comType;
				pdInfo[i].pUserCbFunc = pUserCallBack;

				break;
			}
		}
		if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
			ret = TRDP_MINI_MEM_ERR;
		}

		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}


	return ret;
}

/**********************************************************************************************************************/
/** unsubscribe one comId, release the specified communication block for receiving the specified comId data
 * */
TRDP_MINI_ERR_T trdp_mini_pd_unsubscribe(INT32U comId)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if(comId == 0){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){

		for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
			if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == comId)){
				if(pdInfo[i].pMemory != NULL){
					switch(pdInfo[i].blockSize){
#if TRDP_MINI_BLKCNT_16B > 0
					case 16:
						((struct m16B_T *)pdInfo[i].pMemory)->isValid = 0;
						break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
					case 32:
						((struct m32B_T *)pdInfo[i].pMemory)->isValid = 0;
						break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
					case 64:
						((struct m64B_T *)pdInfo[i].pMemory)->isValid = 0;
						break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
					case 128:
						((struct m128B_T *)pdInfo[i].pMemory)->isValid = 0;
						break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
					case 256:
						((struct m256B_T *)pdInfo[i].pMemory)->isValid = 0;
						break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
					case 512:
						((struct m512B_T *)pdInfo[i].pMemory)->isValid = 0;
						break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
					case 1024:
						((struct m1024B_T *)pdInfo[i].pMemory)->isValid = 0;
						break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
					case 1348:
						((struct m1348B_T *)pdInfo[i].pMemory)->isValid = 0;
						break;
#endif
					default:
						break;
					}
				}
				memset(&pdInfo[i], 0, sizeof(pdInfo[i]));
				break;
			}
		}
		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
		ret = TRDP_MINI_NOSESSION_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** trdp_mini_pd_poll
 *  poll data by comId
 *
 *  @param[in]      comId               comId that indicate the data source
 *  @param[out]     pData               data buffer that hold the data
 *  @param[out]     dataSize            the length of data size in byte
 *
 *  @retval         TRDP_INIT_ERR       no error or error
 */
TRDP_MINI_ERR_T trdp_mini_pd_poll(INT32U comId, INT8U *pData, INT32U *dataSize, INT8U *pDestIP)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if(pData == NULL){
		return TRDP_MINI_PARAM_ERR;
	}
    *dataSize = 0;
	if(vos_PcbSemaphoreTake() == OK){
		for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
			if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == comId) && (memcmp(pdInfo[i].destIpAddr, pDestIP, 4) == 0)){
				//we find the specified control block
				if(pdInfo[i].blockSize > 0){
					//load the data size
					*dataSize = pdInfo[i].dataSize;
					switch(pdInfo[i].blockSize){
#if TRDP_MINI_BLKCNT_16B > 0
					case 16:
						memcpy( pData, ((struct m16B_T *)pdInfo[i].pMemory)->data, (int)pdInfo[i].dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
					case 32:
						memcpy( pData, ((struct m32B_T *)pdInfo[i].pMemory)->data, (int)pdInfo[i].dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
					case 64:
						memcpy( pData, ((struct m64B_T *)pdInfo[i].pMemory)->data, (int)pdInfo[i].dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
					case 128:
						memcpy( pData, ((struct m128B_T *)pdInfo[i].pMemory)->data, (int)pdInfo[i].dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
					case 256:
						memcpy( pData, ((struct m256B_T *)pdInfo[i].pMemory)->data, (int)pdInfo[i].dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
					case 512:
						memcpy( pData, ((struct m512B_T *)pdInfo[i].pMemory)->data, (int)pdInfo[i].dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
					case 1024:
						memcpy( pData, ((struct m1024B_T *)pdInfo[i].pMemory)->data, (int)pdInfo[i].dataSize);
						break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
					case 1348:
						memcpy( pData, ((struct m1348B_T *)pdInfo[i].pMemory)->data, (int)pdInfo[i].dataSize);
						break;
#endif
					default:
						ret = TRDP_MINI_PARAM_ERR;
						break;
					}
				}else{
					ret = TRDP_MINI_NODATA_ERR;
				}
				//get out the loop
				break;
			}
		}
        if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
            //we can't find the specified comId
            ret = TRDP_MINI_COMID_ERR;
        }
		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** trdp_mini_pd_poll
 *  poll data by comId
 *
 *  @param[in]      comId               comId that indicate the data source
 *  @param[out]     pData               data buffer that hold the data
 *  @param[out]     dataSize            the length of data size in byte
 *
 *  @retval         TRDP_INIT_ERR       no error or error
 */
void trdp_mini_Receive_CallBack(void *arg, INT8U *pData, INT32U dataSize, INT8U *pRecvIp, INT16U recvPort)
{
	INT16U *pU16=NULL, msgType;

	if(vos_PcbSemaphoreTake() == OK){
        pU16 = (INT16U *)&pData[6];     //get the message type
				msgType = *pU16;
		if(sIsBigEndian != TRDP_MINI_USE_BIG_ENDIAN){
			//we revert the data header that we get and reserve the data for user
			msgType = trdp_mini_until_RvINT16U(msgType);
		}

		if(msgType > 0x5000){
			//PD message call back
			receive_pd_callBack(arg, pData, dataSize, pRecvIp, recvPort);
		}else{
			//MD message call back
			receive_md_callBack(arg, pData, dataSize, pRecvIp, recvPort);
		}

		vos_PcbSemaphoreGive();
	}

}

/*--------------------------------------------MD package process------------------------------------------------------*/
/**********************************************************************************************************************/
/** MD request
 * */
TRDP_MINI_ERR_T trdp_mini_md_request(INT32U comId,  INT8U *pData, INT32U dataSize, INT8U *pSrcIP, INT8U *pDestIP, INT32U etbTopoCnt, INT32U timeOut, BOOLEAN needReply,INT8S *srcURI, INT8S *destURI, TRDP_MINI_MD_CALLBACK_T pUserCallBack)
{
	int i = 0, m = 0, b = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;
	INT32U  blockSize[TRDP_MINI_NBK_SIZES] = TRDP_MINI_MEM_BLKSIZE;

	if((pSrcIP == NULL) || (pDestIP == NULL) || (pUserCallBack == NULL)){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){
		for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
			if((mdInfo[i].flagBits & FLAGS_ENABLE) == 0){
				/* prepare the memory block for the update data*/
				if(dataSize > 0 && pData != NULL){
					for(m = 0; m < TRDP_MINI_NBK_SIZES; m++){
						if(blockSize[m] >=  dataSize){
							/*find one block class can hold the data*/
							switch(blockSize[m]){
#if TRDP_MINI_BLKCNT_16B > 0
							case 16:
								for(b=0; b<TRDP_MINI_BLKCNT_16B; b++){
									if(gMem.mb16B[b].isValid == 0){
                                        gMem.mb16B[b].isValid = 1;
										memcpy(gMem.mb16B[b].data, pData, (int)dataSize);
										mdInfo[i].pMemory = (void *)&gMem.mb16B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
							case 32:
								for(b=0; b<TRDP_MINI_BLKCNT_32B; b++){
									if(gMem.mb32B[b].isValid == 0){
                                        gMem.mb32B[b].isValid = 1;
										memcpy(gMem.mb32B[b].data, pData, (int)dataSize);
										mdInfo[i].pMemory = (void *)&gMem.mb32B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
							case 64:
								for(b=0; b<TRDP_MINI_BLKCNT_64B; b++){
									if(gMem.mb64B[b].isValid == 0){
                                        gMem.mb64B[b].isValid = 1;
										memcpy(gMem.mb64B[b].data, pData, (int)dataSize);
										mdInfo[i].pMemory = (void *)&gMem.mb64B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
							case 128:
								for(b=0; b<TRDP_MINI_BLKCNT_128B; b++){
									if(gMem.mb128B[b].isValid == 0){
                                        gMem.mb128B[b].isValid = 1;
										memcpy(gMem.mb128B[b].data, pData, (int)dataSize);
										mdInfo[i].pMemory = (void *)&gMem.mb128B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
							case 256:
								for(b=0; b<TRDP_MINI_BLKCNT_256B; b++){
									if(gMem.mb256B[b].isValid == 0){
                                        gMem.mb256B[b].isValid = 1;
										memcpy(gMem.mb256B[b].data, pData, (int)dataSize);
										mdInfo[i].pMemory = (void *)&gMem.mb256B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
							case 512:
								for(b=0; b<TRDP_MINI_BLKCNT_512B; b++){
									if(gMem.mb512B[b].isValid == 0){
                                        gMem.mb512B[b].isValid = 1;
										memcpy(gMem.mb512B[b].data, pData, (int)dataSize);
										mdInfo[i].pMemory = (void *)&gMem.mb512B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
							case 1024:
								for(b=0; b<TRDP_MINI_BLKCNT_1024B; b++){
									if(gMem.mb1024B[b].isValid == 0){
                                        gMem.mb1024B[b].isValid = 1;
										memcpy(gMem.mb1024B[b].data, pData, (int)dataSize);
										mdInfo[i].pMemory = (void *)&gMem.mb1024B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
							case 1348:
								for(b=0; b<TRDP_MINI_BLKCNT_1348B; b++){
									if(gMem.mb1348B[b].isValid == 0){
                                        gMem.mb1348B[b].isValid = 1;
										memcpy(gMem.mb1348B[b].data, pData, (int)dataSize);
										mdInfo[i].pMemory = (void *)&gMem.mb1348B[b];
										break;
									}
								}
								break;
#endif
							default:
								break;
							}
							if(mdInfo[i].pMemory != NULL){
								mdInfo[i].blockSize = blockSize[m];
								/*we find one unused PD control block*/
								mdInfo[i].flagBits |= FLAGS_ENABLE;						//active this MD control block
								mdInfo[i].seqCount = mdSeqID;
								mdSeqID++;
								mdInfo[i].comId = comId;								//initialize the PD info
								mdInfo[i].dataSize = dataSize;							//initialize the datasize
								memcpy(mdInfo[i].srcIpAddr, pSrcIP, sizeof(mdInfo[i].srcIpAddr));
								memcpy(mdInfo[i].destIpAddr, pDestIP, sizeof(mdInfo[i].destIpAddr));
								mdInfo[i].etbTopoCnt = etbTopoCnt;
								mdInfo[i].interval = timeOut;
								mdInfo[i].msgType = (needReply == TRUE)?TRDP_MINI_MSG_MR:TRDP_MINI_MSG_MN;
								mdInfo[i].pUserCbFunc = pUserCallBack;

								memcpy(mdInfo[i].srcURI, srcURI, sizeof(mdInfo[i].srcURI));
								memcpy(mdInfo[i].destURI, destURI, sizeof(mdInfo[i].destURI));

								if(vos_getSessionID(mdInfo[i].sessionId, i) == ERROR){
									ret = TRDP_MINI_NOSESSION_ERR;
								}else{
									if(OSQPostOpt(pSendMdMsg, (void *)&mdInfo[i], OS_POST_OPT_NONE) != OK){
										ret = TRDP_MINI_QUEUE_FULL_ERR;
									}else{
										trdp_mini_process();
									}
								}
								//break out if we find one
								break;
							}
						}
					}
				}else{
					/*we find a PD Control block to hold our request */
					mdInfo[i].flagBits |= FLAGS_ENABLE;						//active this PD control block
					mdInfo[i].comId = comId;								//initialize the PD info

					memcpy(mdInfo[i].srcIpAddr, pSrcIP, sizeof(mdInfo[i].srcIpAddr));
					memcpy(mdInfo[i].destIpAddr, pDestIP, sizeof(mdInfo[i].destIpAddr));

					mdInfo[i].etbTopoCnt = etbTopoCnt;
					mdInfo[i].interval = timeOut;
					mdInfo[i].msgType = (needReply == TRUE)?TRDP_MINI_MSG_MR:TRDP_MINI_MSG_MN;
					mdInfo[i].pUserCbFunc = pUserCallBack;

					memcpy(mdInfo[i].srcURI, srcURI, sizeof(mdInfo[i].srcURI));
					memcpy(mdInfo[i].destURI, destURI, sizeof(mdInfo[i].destURI));

					if(vos_getSessionID(mdInfo[i].sessionId, i) == ERROR){
						ret = TRDP_MINI_NOSESSION_ERR;
					}else{
						if(OSQPostOpt(pSendMdMsg, (void *)&mdInfo[i], OS_POST_OPT_NONE) != OK){
							ret = TRDP_MINI_QUEUE_FULL_ERR;
						}else{
							trdp_mini_process();
						}
					}
					break;
				}
				break;
			}
		}
		if(i == TRDP_MINI_MD_CTRL_MAX_NUM){
			ret = TRDP_MINI_MEM_ERR;
		}
		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** MD confirm
 * */
TRDP_MINI_ERR_T trdp_mini_md_confirm(INT32U comId, INT8U *pSrcIP, INT8U *pDestIP, INT32U etbTopoCnt,INT8S *srcURI, INT8S *destURI, INT8U *pSessionId, INT32U replyStatus, INT32U seqCnt)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if((pSrcIP == NULL) || (pDestIP == NULL)){
		return TRDP_MINI_PARAM_ERR;
	}


	for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
		if((mdInfo[i].flagBits & FLAGS_ENABLE) == 0){
			/*we find a PD Control block to hold our request */
			mdInfo[i].flagBits |= FLAGS_ENABLE;						//active this PD control block
			mdInfo[i].comId = comId;								//initialize the PD info

			memcpy(mdInfo[i].srcIpAddr, pSrcIP, sizeof(mdInfo[i].srcIpAddr));
			memcpy(mdInfo[i].destIpAddr, pDestIP, sizeof(mdInfo[i].destIpAddr));
			mdInfo[i].etbTopoCnt = etbTopoCnt;
			mdInfo[i].msgType = TRDP_MINI_MSG_MC;
			memcpy(mdInfo[i].sessionId, pSessionId, sizeof(mdInfo[i].sessionId));
			mdInfo[i].userStatus = replyStatus;
			mdInfo[i].seqCount = seqCnt;
			memcpy(mdInfo[i].srcURI, srcURI, (strlen((char *)srcURI)<sizeof(mdInfo[i].srcURI))?strlen((char *)srcURI):sizeof(mdInfo[i].srcURI));
			memcpy(mdInfo[i].destURI, destURI, (strlen((char *)destURI)<sizeof(mdInfo[i].destURI))?strlen((char *)destURI):sizeof(mdInfo[i].destURI));

			if(OSQPostOpt(pSendMdMsg, (void *)&mdInfo[i], OS_POST_OPT_NONE) != OK){
				ret = TRDP_MINI_QUEUE_FULL_ERR;
			}else{
				trdp_mini_process();
			}

			break;
		}
	}
	if(i == TRDP_MINI_MD_CTRL_MAX_NUM){
		ret = TRDP_MINI_MEM_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** MD reply
 * */
TRDP_MINI_ERR_T trdp_mini_md_reply(INT32U comId,  INT8U *pData, INT32U dataSize, INT8U *pSrcIP, INT8U *pDestIP, INT32U etbTopoCnt, INT32U timeOut, BOOLEAN needConfirm,INT8S *srcURI, INT8S *destURI, INT8U *pSessionId, INT32U replyStatus, INT32U seqCnt, TRDP_MINI_MD_CALLBACK_T pUserCallBack)
{
	int i = 0, m = 0, b = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;
	INT32U  blockSize[TRDP_MINI_NBK_SIZES] = TRDP_MINI_MEM_BLKSIZE;

	if((pSrcIP == NULL) || (pDestIP == NULL) || (pUserCallBack == NULL)){
		return TRDP_MINI_PARAM_ERR;
	}


	for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
		if((mdInfo[i].flagBits & FLAGS_ENABLE) == 0){
			/* prepare the memory block for the update data*/
			if(dataSize > 0 && pData != NULL){
				for(m = 0; m < TRDP_MINI_NBK_SIZES; m++){
					if(blockSize[m] >=  dataSize){
						/*find one block class can hold the data*/
						switch(blockSize[m]){
#if TRDP_MINI_BLKCNT_16B > 0
						case 16:
							for(b=0; b<TRDP_MINI_BLKCNT_16B; b++){
								if(gMem.mb16B[b].isValid == 0){
									gMem.mb16B[b].isValid = 1;
									memcpy(gMem.mb16B[b].data, pData, (int)dataSize);
									mdInfo[i].pMemory = (void *)&gMem.mb16B[b];
									break;
								}
							}
							break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
						case 32:
							for(b=0; b<TRDP_MINI_BLKCNT_32B; b++){
								if(gMem.mb32B[b].isValid == 0){
									gMem.mb32B[b].isValid = 1;
									memcpy(gMem.mb32B[b].data, pData, (int)dataSize);
									mdInfo[i].pMemory = (void *)&gMem.mb32B[b];
									break;
								}
							}
							break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
						case 64:
							for(b=0; b<TRDP_MINI_BLKCNT_64B; b++){
								if(gMem.mb64B[b].isValid == 0){
									gMem.mb64B[b].isValid = 1;
									memcpy(gMem.mb64B[b].data, pData, (int)dataSize);
									mdInfo[i].pMemory = (void *)&gMem.mb64B[b];
									break;
								}
							}
							break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
						case 128:
							for(b=0; b<TRDP_MINI_BLKCNT_128B; b++){
								if(gMem.mb128B[b].isValid == 0){
									gMem.mb128B[b].isValid = 1;
									memcpy(gMem.mb128B[b].data, pData, (int)dataSize);
									mdInfo[i].pMemory = (void *)&gMem.mb128B[b];
									break;
								}
							}
							break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
						case 256:
							for(b=0; b<TRDP_MINI_BLKCNT_256B; b++){
								if(gMem.mb256B[b].isValid == 0){
									gMem.mb256B[b].isValid = 1;
									memcpy(gMem.mb256B[b].data, pData, (int)dataSize);
									mdInfo[i].pMemory = (void *)&gMem.mb256B[b];
									break;
								}
							}
							break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
						case 512:
							for(b=0; b<TRDP_MINI_BLKCNT_512B; b++){
								if(gMem.mb512B[b].isValid == 0){
									gMem.mb512B[b].isValid = 1;
									memcpy(gMem.mb512B[b].data, pData, (int)dataSize);
									mdInfo[i].pMemory = (void *)&gMem.mb512B[b];
									break;
								}
							}
							break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
						case 1024:
							for(b=0; b<TRDP_MINI_BLKCNT_1024B; b++){
								if(gMem.mb1024B[b].isValid == 0){
									gMem.mb1024B[b].isValid = 1;
									memcpy(gMem.mb1024B[b].data, pData, (int)dataSize);
									mdInfo[i].pMemory = (void *)&gMem.mb1024B[b];
									break;
								}
							}
							break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
						case 1348:
							for(b=0; b<TRDP_MINI_BLKCNT_1348B; b++){
								if(gMem.mb1348B[b].isValid == 0){
									gMem.mb1348B[b].isValid = 1;
									memcpy(gMem.mb1348B[b].data, pData, (int)dataSize);
									mdInfo[i].pMemory = (void *)&gMem.mb1348B[b];
									break;
								}
							}
							break;
#endif
						default:
							break;
						}
						if(mdInfo[i].pMemory != NULL){
							mdInfo[i].blockSize = blockSize[m];
							/*we find one unused PD control block*/
							mdInfo[i].flagBits |= FLAGS_ENABLE;						//active this MD control block
							mdInfo[i].comId = comId;								//initialize the PD info
							mdInfo[i].dataSize = dataSize;							//initialize the datasize
							memcpy(mdInfo[i].srcIpAddr, pSrcIP, sizeof(mdInfo[i].srcIpAddr));
							memcpy(mdInfo[i].destIpAddr, pDestIP, sizeof(mdInfo[i].destIpAddr));
							mdInfo[i].etbTopoCnt = etbTopoCnt;
							mdInfo[i].interval = timeOut;
							mdInfo[i].msgType = (needConfirm == TRUE)?TRDP_MINI_MSG_MQ:TRDP_MINI_MSG_MP;
							mdInfo[i].pUserCbFunc = pUserCallBack;

							mdInfo[i].userStatus = replyStatus;
							mdInfo[i].seqCount = seqCnt;
							memcpy(mdInfo[i].srcURI, srcURI, sizeof(mdInfo[i].srcURI));
							memcpy(mdInfo[i].destURI, destURI, sizeof(mdInfo[i].destURI));
							memcpy(mdInfo[i].sessionId, pSessionId, sizeof(mdInfo[i].sessionId));
							if(OSQPostOpt(pSendMdMsg, (void *)&mdInfo[i], OS_POST_OPT_NONE) != OK){
								ret = TRDP_MINI_QUEUE_FULL_ERR;
							}else{
								ret = TRDP_MINI_NO_ERR;
								trdp_mini_process();
							}

							//break out if we find one
							break;
						}
					}
				}
			}else{
				/*we find a PD Control block to hold our request */
				mdInfo[i].flagBits |= FLAGS_ENABLE;						//active this PD control block
				mdInfo[i].comId = comId;								//initialize the PD info

				memcpy(mdInfo[i].srcIpAddr, pSrcIP, sizeof(mdInfo[i].srcIpAddr));
				memcpy(mdInfo[i].destIpAddr, pDestIP, sizeof(mdInfo[i].destIpAddr));

				mdInfo[i].etbTopoCnt = etbTopoCnt;
				mdInfo[i].interval = timeOut;
				mdInfo[i].msgType = (needConfirm == TRUE)?TRDP_MINI_MSG_MQ:TRDP_MINI_MSG_MP;
				mdInfo[i].pUserCbFunc = pUserCallBack;

				mdInfo[i].userStatus = replyStatus;
				mdInfo[i].seqCount = seqCnt;
				memcpy(mdInfo[i].srcURI, srcURI, sizeof(mdInfo[i].srcURI));
				memcpy(mdInfo[i].destURI, destURI, sizeof(mdInfo[i].destURI));
				memcpy(mdInfo[i].sessionId, pSessionId, sizeof(mdInfo[i].sessionId));
				if(OSQPostOpt(pSendMdMsg, (void *)&mdInfo[i], OS_POST_OPT_NONE) != OK){
					ret = TRDP_MINI_QUEUE_FULL_ERR;
				}else{
					trdp_mini_process();
				}
				break;
			}
			break;
		}
	}
	if(i == TRDP_MINI_MD_CTRL_MAX_NUM){
		ret = TRDP_MINI_MEM_ERR;
	}


	return ret;
}




/**********************************************************************************************************************/
/** MD abort
 * */
TRDP_MINI_ERR_T trdp_mini_md_abort(INT32U comId)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if(vos_PcbSemaphoreTake() == OK){
		for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
			if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (mdInfo[i].comId == comId)){
				if(vos_abortTCPConnection(mdInfo[i].srcIpAddr, mdInfo[i].destIpAddr) == ERROR){
					ret = TRDP_MINI_NOCONN_ERR;
				}else{
					//make the message data invalid
					if(mdInfo[i].pMemory != NULL){
						*((INT32U *)mdInfo[i].pMemory) = 0;
					}
					memset(&mdInfo[i], 0 , sizeof(mdInfo[i]));
				}
			}
		}
		if(i == TRDP_MINI_MD_CTRL_MAX_NUM){
			ret = TRDP_MINI_COMID_ERR;
		}

		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** MD add listener
 * */
TRDP_MINI_ERR_T trdp_mini_md_addListener(INT32U comId, INT8U *pSrcIP, INT8U *pDestIP, TRDP_MINI_MD_CALLBACK_T pUserCallBack)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if((pSrcIP == NULL) || (pDestIP == NULL) || (pUserCallBack == NULL)){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){
		for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
			if((mdInfo[i].flagBits & FLAGS_ENABLE) == 0){
				/*we find a MD Control block to hold our request */
				mdInfo[i].flagBits |= FLAGS_ENABLE|FLAGS_MODE;						//active this MD control block
				mdInfo[i].comId = comId;								//initialize the PD info
				memcpy(mdInfo[i].srcIpAddr, pSrcIP, sizeof(mdInfo[i].srcIpAddr));
				memcpy(mdInfo[i].destIpAddr, pDestIP, sizeof(mdInfo[i].destIpAddr));
				mdInfo[i].pUserCbFunc = pUserCallBack;

				break;
			}
		}
		if(i == TRDP_MINI_MD_CTRL_MAX_NUM){
			ret = TRDP_MINI_MEM_ERR;
		}

		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}


	return ret;
}

/**********************************************************************************************************************/
/** MD remove listener
 * */
TRDP_MINI_ERR_T trdp_mini_md_removeListener(INT32U comId)
{
	int i = 0;
	TRDP_MINI_ERR_T ret = TRDP_MINI_NO_ERR;

	if(comId == 0){
		return TRDP_MINI_PARAM_ERR;
	}

	if(vos_PcbSemaphoreTake() == OK){

		for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
			if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (mdInfo[i].comId == comId)){
				if(pdInfo[i].pMemory != NULL){
					*((INT32U *)mdInfo[i].pMemory) = 0;
				}

				memset(&mdInfo[i], 0, sizeof(mdInfo[i]));
				break;
			}
		}
		vos_PcbSemaphoreGive();
	}else{
		ret = TRDP_MINI_SEMA_ERR;
	}

	if(i == TRDP_MINI_PD_CTRL_MAX_NUM){
		ret = TRDP_MINI_NOSESSION_ERR;
	}

	return ret;
}

/**********************************************************************************************************************/
/** TRDP Process for PD and MD package conduct
 * */
void trdp_mini_process(void)
{
	int i = 0;

	PD_INFO_T	*pBlk_PD = NULL;
	MD_INFO_T	*pBlk_MD = NULL;

	TRDP_MINI_PD_HEAD_T *pHead_PD = NULL;
	TRDP_MINI_MD_HEADER_T *pHead_MD = NULL;
	INT8U *pData = NULL;

	/*------------------process the process data sending data in the queue--------------------*/
	while(TRUE){
		//we should process all the sending data in the queue
		pBlk_PD = (PD_INFO_T *)OSQAccept(pSendPdMsg);
		if(pBlk_PD != NULL){
			//we find one block should be transmit to network
			pHead_PD = (TRDP_MINI_PD_HEAD_T *)udpData;
			pData = (INT8U *)(udpData+sizeof(TRDP_MINI_PD_HEAD_T));
			//generate header
			pHead_PD->sequenceCounter = pBlk_PD->seqCount;
			pHead_PD->protocolVersion = TRDP_MINI_PROTOCOL_VER;
			pHead_PD->msgType = pBlk_PD->msgType;
			pHead_PD->comId = pBlk_PD->comId;
			pHead_PD->etbTopoCnt = pBlk_PD->etbTopoCnt;
			pHead_PD->localTopoCnt = gLocolTopoCnt;
			pHead_PD->datasetLength = pBlk_PD->dataSize;
			pHead_PD->replyComId = pBlk_PD->replyComId;
			memcpy(pHead_PD->replyIpAddress, pBlk_PD->replyIpAddr, sizeof(pBlk_PD->replyIpAddr));
			//pHead_PD->frameCheckSum = vos_crc32(INITFCS, (INT8U *)pHead_PD, sizeof(TRDP_MINI_PD_HEAD_T)-SIZE_OF_FCS);


			if(sIsBigEndian != TRDP_MINI_USE_BIG_ENDIAN){
				pHead_PD->sequenceCounter = trdp_mini_until_RvINT32U(pHead_PD->sequenceCounter);
				pHead_PD->protocolVersion = trdp_mini_until_RvINT16U(pHead_PD->protocolVersion);
				pHead_PD->msgType		  = trdp_mini_until_RvINT16U(pHead_PD->msgType);
				pHead_PD->comId			  = trdp_mini_until_RvINT32U(pHead_PD->comId);
				pHead_PD->etbTopoCnt	  = trdp_mini_until_RvINT32U(pHead_PD->etbTopoCnt);
				pHead_PD->localTopoCnt	  = trdp_mini_until_RvINT32U(pHead_PD->localTopoCnt);
				pHead_PD->datasetLength	  = trdp_mini_until_RvINT32U(pHead_PD->datasetLength);
				pHead_PD->replyComId 	  = trdp_mini_until_RvINT32U(pHead_PD->replyComId);
				pHead_PD->frameCheckSum = vos_crc32(INITFCS, (INT8U *)pHead_PD, sizeof(TRDP_MINI_PD_HEAD_T)-SIZE_OF_FCS);
			}else{
				pHead_PD->frameCheckSum = trdp_mini_until_RvINT32U(vos_crc32(INITFCS, (INT8U *)pHead_PD, sizeof(TRDP_MINI_PD_HEAD_T)-SIZE_OF_FCS));
			}
			//generate user data
			memcpy(pData, ((INT8U *)pBlk_PD->pMemory+4), pBlk_PD->dataSize);

			//send data
			if(pBlk_PD->comType == COM_UDP_UNICAST){
				if(vos_sendUDPUnicast(pBlk_PD->srcIpAddr, pBlk_PD->destIpAddr, TRDP_MINI_PD_UDP_PORT, udpData, (sizeof(TRDP_MINI_PD_HEAD_T)+pBlk_PD->dataSize)) == ERROR){
					if(pBlk_PD->pUserCbFunc != NULL){
						pBlk_PD->pUserCbFunc(NULL, pBlk_PD->comId, NULL, 0, NULL, TRDP_MINI_PD_UDP_PORT, TRDP_MINI_IO_ERR);
					}
				}
			}else if(pBlk_PD->comType == COM_UDP_MULTICAST){
				if(vos_sendUDPMulticast(pBlk_PD->srcIpAddr, pBlk_PD->destIpAddr, TRDP_MINI_PD_UDP_PORT, udpData, (sizeof(TRDP_MINI_PD_HEAD_T)+pBlk_PD->dataSize)) == ERROR){
					if(pBlk_PD->pUserCbFunc != NULL){
						pBlk_PD->pUserCbFunc(NULL, pBlk_PD->comId, NULL, 0, NULL, TRDP_MINI_PD_UDP_PORT, TRDP_MINI_IO_ERR);
					}
				}
			}else if(pBlk_PD->comType == COM_UDP_BROADCAST){
				if(vos_sendUDPBroadcast(pBlk_PD->srcIpAddr, pBlk_PD->destIpAddr, TRDP_MINI_PD_UDP_PORT, udpData, (sizeof(TRDP_MINI_PD_HEAD_T)+pBlk_PD->dataSize)) == ERROR){
					if(pBlk_PD->pUserCbFunc != NULL){
						pBlk_PD->pUserCbFunc(NULL, pBlk_PD->comId, NULL, 0, NULL, TRDP_MINI_PD_UDP_PORT, TRDP_MINI_IO_ERR);
					}
				}
			}else{
				if(pBlk_PD->pUserCbFunc != NULL){
					pBlk_PD->pUserCbFunc(NULL, pBlk_PD->comId, NULL, 0, NULL, TRDP_MINI_PD_UDP_PORT, TRDP_MINI_PARAM_ERR);
				}
			}

			if(pBlk_PD->msgType == TRDP_MINI_MSG_PP){
				//release the pdInfo if the message is the reply block
				if(pBlk_PD->pMemory != NULL){
					//make the memory block invalid
					*((INT32U *)pBlk_PD->pMemory) = 0;
				}
				memset(pBlk_PD, 0, sizeof(PD_INFO_T));
			}else if(pBlk_PD->msgType == TRDP_MINI_MSG_PR){
				pBlk_PD->lastTimerCnt = gMsTimerCnt;			//set the start time when we send the data
			}else{
			    pBlk_PD->seqCount++;
			}
		}else{
			//we break out if the queue is empty
			break;
		}
	}
	/*------------------process the message sending data in the queue--------------------*/
	while(TRUE){
		//we should process all the message sending data in the queue
		pBlk_MD = (MD_INFO_T *)OSQAccept(pSendMdMsg);
		if(pBlk_MD != NULL){
			//we find one block should be transmit to network
			pHead_MD = (TRDP_MINI_MD_HEADER_T *)tcpData;
			pData = (INT8U *)(tcpData+sizeof(TRDP_MINI_MD_HEADER_T));
			//generate header
			pHead_MD->sequenceCounter = pBlk_MD->seqCount;
			pHead_MD->protocolVersion = TRDP_MINI_PROTOCOL_VER;
			pHead_MD->msgType = pBlk_MD->msgType;
			pHead_MD->comId = pBlk_MD->comId;
			pHead_MD->etbTopoCnt = pBlk_MD->etbTopoCnt;
			pHead_MD->localTopoCnt = gLocolTopoCnt;
			pHead_MD->datasetLength = pBlk_MD->dataSize;
			pHead_MD->replyStatus = pBlk_MD->userStatus;

			memcpy(pHead_MD->sessionID, pBlk_MD->sessionId, sizeof(pBlk_MD->sessionId));
			pHead_MD->replyTimeout = pBlk_MD->interval;
			memcpy(pHead_MD->sourceURI, pBlk_MD->srcURI, sizeof(pBlk_MD->srcURI));
			memcpy(pHead_MD->destinationURI, pBlk_MD->destURI, sizeof(pBlk_MD->destURI));
			//pHead_MD->frameCheckSum = vos_crc32(INITFCS, (INT8U *)pHead_MD, sizeof(TRDP_MINI_MD_HEADER_T)-SIZE_OF_FCS);

			if(sIsBigEndian != TRDP_MINI_USE_BIG_ENDIAN){
				pHead_MD->sequenceCounter = trdp_mini_until_RvINT32U(pHead_MD->sequenceCounter);
				pHead_MD->protocolVersion = trdp_mini_until_RvINT16U(pHead_MD->protocolVersion);
				pHead_MD->msgType		  = trdp_mini_until_RvINT16U(pHead_MD->msgType);
				pHead_MD->comId		  	  = trdp_mini_until_RvINT32U(pHead_MD->comId);
				pHead_MD->etbTopoCnt	  = trdp_mini_until_RvINT32U(pHead_MD->etbTopoCnt);
				pHead_MD->localTopoCnt	  = trdp_mini_until_RvINT32U(pHead_MD->localTopoCnt);
				pHead_MD->datasetLength	  = trdp_mini_until_RvINT32U(pHead_MD->datasetLength);
				pHead_MD->replyStatus     = trdp_mini_until_RvINT32U(pHead_MD->replyStatus);
				pHead_MD->replyTimeout	  = trdp_mini_until_RvINT32U(pHead_MD->replyTimeout);
				pHead_MD->frameCheckSum = vos_crc32(INITFCS, (INT8U *)pHead_MD, sizeof(TRDP_MINI_MD_HEADER_T)-SIZE_OF_FCS);
			}else{
				pHead_MD->frameCheckSum = trdp_mini_until_RvINT32U(vos_crc32(INITFCS, (INT8U *)pHead_MD, sizeof(TRDP_MINI_MD_HEADER_T)-SIZE_OF_FCS));
			}
			//generate user data
			memcpy(pData, ((INT8U *)pBlk_MD->pMemory+4), pBlk_MD->dataSize);
			//send data
			if(vos_sendTCPMessage(pBlk_MD->srcIpAddr, pBlk_MD->destIpAddr, TRDP_MINI_MD_TCP_PORT, tcpData, (sizeof(TRDP_MINI_MD_HEADER_T)+pBlk_MD->dataSize)) == ERROR){
				if(pBlk_MD->pUserCbFunc != NULL){
					pBlk_MD->pUserCbFunc(NULL, pBlk_MD->comId,MD_DO_NOTHING, NULL, 0,
							pBlk_MD->etbTopoCnt, pBlk_MD->sessionId, pBlk_MD->srcURI, pBlk_MD->destURI, pBlk_MD->seqCount, NULL, TRDP_MINI_MD_TCP_PORT, TRDP_MINI_IO_ERR);
				}
			}

			if((pBlk_MD->msgType == TRDP_MINI_MSG_MN) || (pBlk_MD->msgType == TRDP_MINI_MSG_MP) ||(pBlk_MD->msgType == TRDP_MINI_MSG_MC)){
				//release the md control block if this transmition don't need replay
				if(pBlk_MD->pMemory != NULL){
					//make the memory block invalid
					*((INT32U *)pBlk_MD->pMemory) = 0;
				}
				memset(pBlk_MD, 0, sizeof(MD_INFO_T));
			}else{
				pBlk_MD->lastTimerCnt = gMsTimerCnt;		//record the send timestamp
			}
		}else{
			//we break out if the queue is empty
			break;
		}
	}


	/*-----------------------------process PD messages block------------------------------------*/
		for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
			if((pdInfo[i].flagBits & FLAGS_ENABLE) > 0){
				//find one process control block
				if((pdInfo[i].flagBits & FLAGS_MODE) == 0){
					//we should process the data that should be sent
					if((pdInfo[i].flagBits & FLAGS_AUTO) == 0){
						//check the timeout
						if(waitMsTicks(pdInfo[i].lastTimerCnt, pdInfo[i].interval) == OK){
							//timeout happened we should release the block memory
							if(pdInfo[i].pUserCbFunc != NULL){
								pdInfo[i].pUserCbFunc(NULL, pdInfo[i].comId, NULL, 0, NULL, TRDP_MINI_PD_UDP_PORT, TRDP_MINI_TIMEOUT_ERR);
							}
							//release the pdInfo if the message is the reply block
							if(pdInfo[i].pMemory != NULL){
								//make the memory block invalid
								*((INT32U *)pdInfo[i].pMemory) = 0;
							}
							memset(&pdInfo[i], 0, sizeof(PD_INFO_T));
						}
					}
				}
			}
		}

		/*-----------------------------process MD messages block------------------------------------*/
		for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
			if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) && ((mdInfo[i].flagBits & FLAGS_MODE) == 0)){
	            if(waitMsTicks(mdInfo[i].lastTimerCnt, mdInfo[i].interval) == OK){
	                mdInfo[i].pUserCbFunc(NULL, mdInfo[i].comId, MD_DO_NOTHING, NULL, 0,
	                        mdInfo[i].etbTopoCnt, mdInfo[i].sessionId, mdInfo[i].srcURI, mdInfo[i].destURI, mdInfo[i].seqCount,NULL, 0, TRDP_MINI_TIMEOUT_ERR);
	                //release this control block
	                if(mdInfo[i].pMemory != NULL){
	                    //make the memory block invalid
	                    *((INT32U *)mdInfo[i].pMemory) = 0;
	                }
	                //release the pdInfo
	                memset(&mdInfo[i], 0, sizeof(mdInfo[i]));
	            }
			}
		}
}

BOOLEAN trdp_mini_until_isBigEndian(void)
{
	return sIsBigEndian;
}

INT32U trdp_mini_until_RvINT32U(INT32U value)
{
    return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
        (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;
}

INT16U trdp_mini_until_RvINT16U(INT16U value)
{
	return ( ((value & 0x00FF) << 8) | ((value & 0xFF00) >> 8));
}

/***********************************************************************************************************************
 * LOCOL FUNCTIONS
 */

static PD_INFO_T* findNewPdEle(void)
{
	int i = 0;
	for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
		if((pdInfo[i].flagBits & FLAGS_ENABLE) == 0){
			return &pdInfo[i];
		}
	}
	return NULL;
}

static INT32U checkPdComId(INT32U comId, INT8U *pDestIP)
{
	int i = 0;

	if((comId == 0) || (pDestIP == NULL)){
		return ERROR;
	}

	for(i = 0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
		/*check this pdInfo valid*/
		if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == comId) && (memcmp(pdInfo[i].destIpAddr, pDestIP, 4) == 0)){
			return ERROR;
		}
	}

	return OK;
}

static INT8U waitMsTicks(INT32U startCnt, INT32U ticks)
{
	if(gMsTimerCnt == startCnt) return ERROR;

	if(gMsTimerCnt > startCnt) {
		if((gMsTimerCnt - startCnt) >= ticks){
			return OK;
		}
	}else{
		if((0xffffffff - startCnt + gMsTimerCnt + 1) >= ticks){
			return OK;
		}
	}

	return ERROR;
}

static void receive_pd_callBack(void *arg, INT8U *pData, INT32U dataSize, INT8U *pRecvIp, INT16U recvPort)
{
	int i = 0, m = 0, b = 0;
	TRDP_MINI_PD_HEAD_T *pHeader = (TRDP_MINI_PD_HEAD_T *)pData;
	PD_INFO_T *pEle = NULL;
	INT32U  blockSize[TRDP_MINI_NBK_SIZES] = TRDP_MINI_MEM_BLKSIZE;

	if(dataSize >= sizeof(TRDP_MINI_PD_HEAD_T)){
		if(sIsBigEndian != TRDP_MINI_USE_BIG_ENDIAN){
			//revert data in header
			pHeader->sequenceCounter = trdp_mini_until_RvINT32U(pHeader->sequenceCounter);
			pHeader->protocolVersion = trdp_mini_until_RvINT16U(pHeader->protocolVersion);
			pHeader->msgType = trdp_mini_until_RvINT16U(pHeader->msgType);
			pHeader->comId = trdp_mini_until_RvINT32U(pHeader->comId);
			pHeader->etbTopoCnt = trdp_mini_until_RvINT32U(pHeader->etbTopoCnt);
			pHeader->localTopoCnt = trdp_mini_until_RvINT32U(pHeader->localTopoCnt);
			pHeader->datasetLength = trdp_mini_until_RvINT32U(pHeader->datasetLength);
			pHeader->replyComId = trdp_mini_until_RvINT32U(pHeader->replyComId);
			pHeader->frameCheckSum = trdp_mini_until_RvINT32U(pHeader->frameCheckSum);
		}

		if(pHeader->msgType == TRDP_MINI_MSG_PR){
			/*  It might be a PULL request      */
			for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
				if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == (pHeader->replyComId == 0?pHeader->comId : pHeader->replyComId))){

					if(pdInfo[i].seqCount == pHeader->sequenceCounter){
						//same seq counter, and we should discard this package
						break;
					}else{
						//update the seq counter here for a new seq package
						pdInfo[i].seqCount = pHeader->sequenceCounter;
					}

					pEle = findNewPdEle();
					pEle->flagBits |= FLAGS_ENABLE;
					pEle->comType = COM_UDP_UNICAST;
					pEle->msgType = TRDP_MINI_MSG_PP;
					memcpy(pEle->replyIpAddr,  pRecvIp, sizeof(pEle->replyIpAddr));
					memcpy(pEle->srcIpAddr,  pHeader->replyIpAddress, sizeof(pEle->srcIpAddr));
					memcpy(pEle->destIpAddr,  pRecvIp, sizeof(pEle->destIpAddr));
					pEle->seqCount = pHeader->sequenceCounter;
					pEle->comId = pdInfo[i].comId;
					pEle->etbTopoCnt = pHeader->localTopoCnt;
					if(pEle != NULL){
						if(dataSize == sizeof(TRDP_MINI_PD_HEAD_T)){
							//read comId request
							pEle->pMemory = pdInfo[i].pMemory;
							pEle->blockSize = pdInfo[i].blockSize;
							pEle->dataSize = pdInfo[i].dataSize;
							pEle->seqCount = pHeader->sequenceCounter;
							//set new pd element to Send Queue
							OSQPostOpt(pSendPdMsg, (void *)&pEle, OS_POST_OPT_NONE);
							trdp_mini_process();
							break;
						}else{
							//write comId request
							if((pdInfo[i].pMemory != NULL) && (pdInfo[i].blockSize >= (dataSize - sizeof(TRDP_MINI_PD_HEAD_T)))){
                                //write request data for prepare data
								pdInfo[i].dataSize = dataSize-sizeof(TRDP_MINI_PD_HEAD_T);
								switch(pdInfo[i].blockSize){
#if TRDP_MINI_BLKCNT_16B > 0
								case 16:
									memcpy( ((struct m16B_T *)pdInfo[i].pMemory)->data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)(dataSize-sizeof(TRDP_MINI_PD_HEAD_T)));
									break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
								case 32:
									memcpy( ((struct m32B_T *)pdInfo[i].pMemory)->data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)(dataSize-sizeof(TRDP_MINI_PD_HEAD_T)));
									break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
								case 64:
									memcpy( ((struct m64B_T *)pdInfo[i].pMemory)->data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)(dataSize-sizeof(TRDP_MINI_PD_HEAD_T)));
									break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
								case 128:
									memcpy( ((struct m128B_T *)pdInfo[i].pMemory)->data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)(dataSize-sizeof(TRDP_MINI_PD_HEAD_T)));
									break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
								case 256:
									memcpy( ((struct m256B_T *)pdInfo[i].pMemory)->data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)(dataSize-sizeof(TRDP_MINI_PD_HEAD_T)));
									break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
								case 512:
									memcpy( ((struct m512B_T *)pdInfo[i].pMemory)->data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)(dataSize-sizeof(TRDP_MINI_PD_HEAD_T)));
									break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
								case 1024:
									memcpy( ((struct m1024B_T *)pdInfo[i].pMemory)->data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)(dataSize-sizeof(TRDP_MINI_PD_HEAD_T)));
									break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
								case 1348:
									memcpy( ((struct m1348B_T *)pdInfo[i].pMemory)->data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)(dataSize-sizeof(TRDP_MINI_PD_HEAD_T)));
									break;
#endif
								default:
									break;
								}
								pEle->pMemory = pdInfo[i].pMemory;
                                pEle->blockSize = pdInfo[i].blockSize;
                                pEle->dataSize = dataSize-sizeof(TRDP_MINI_PD_HEAD_T);
                                pEle->seqCount = pHeader->sequenceCounter;
                                OSQPostOpt(pSendPdMsg, (void *)pEle, OS_POST_OPT_NONE);
                                trdp_mini_process();
							}else{
							    //write data by request for subscribe data, and we should callback to user layer
							    //do we need to hold these data for future use? maybe we do not need to hold these data, for user layer already processed these data
                                if(pdInfo[i].pUserCbFunc != NULL){
                                    //we confirm to the request layer
                                    pEle->resultCode = pdInfo[i].pUserCbFunc(arg, pdInfo[i].comId, pData+sizeof(TRDP_MINI_PD_HEAD_T), dataSize-sizeof(TRDP_MINI_PD_HEAD_T), pRecvIp, recvPort, TRDP_MINI_NO_ERR);
                                    pEle->dataSize = 0;
                                    pEle->seqCount = pHeader->sequenceCounter;
                                    OSQPostOpt(pSendPdMsg, (void *)pEle, OS_POST_OPT_NONE);
                                    trdp_mini_process();
                                }

                            }
						}
					}
					break;
				}
			}
		}else if(pHeader->msgType == TRDP_MINI_MSG_PP){
			/*  It might be a normal reply Data for request comIds and we should call user's callback function   */
			for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
				if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (pdInfo[i].comId == pHeader->comId) && (pdInfo[i].msgType == TRDP_MINI_MSG_PR)){

					if(pdInfo[i].seqCount == pHeader->sequenceCounter){
						//same seq counter, and we should discard this package
						break;
					}else{
						//update the seq counter here for a new seq package
						pdInfo[i].seqCount = pHeader->sequenceCounter;
					}

					if(pdInfo[i].pUserCbFunc != NULL){
						pdInfo[i].pUserCbFunc(arg, pdInfo[i].comId, pData+sizeof(TRDP_MINI_PD_HEAD_T), dataSize-sizeof(TRDP_MINI_PD_HEAD_T), pRecvIp, recvPort, TRDP_MINI_NO_ERR);
						if(pdInfo[i].pMemory != NULL){
							//make the memory block invalid
							*((INT32U *)pdInfo[i].pMemory) = 0;
							pdInfo[i].pMemory = 0;
						}
						//release the pdInfo
						memset(&pdInfo[i], 0, sizeof(pdInfo[i]));
					}
					break;
				}
			}
		}else if(pHeader->msgType == TRDP_MINI_MSG_PD){
			/*  It might be a normal process Data for subscribe comIds      */
			for(i=0; i<TRDP_MINI_PD_CTRL_MAX_NUM; i++){
				if(((pdInfo[i].flagBits & FLAGS_ENABLE) > 0) && ((pdInfo[i].flagBits & FLAGS_MODE) > 0) && (pdInfo[i].comId == pHeader->comId)){

					if(pdInfo[i].seqCount == pHeader->sequenceCounter){
						//same seq counter, and we should discard this package
						break;
					}else{
						//update the seq counter here for a new seq package
						pdInfo[i].seqCount = pHeader->sequenceCounter;
					}

					if(pdInfo[i].pMemory != NULL){
						//make the memory block invalid
						*((INT32U *)pdInfo[i].pMemory) = 0;
						pdInfo[i].pMemory = NULL;
					}
					/* prepare the memory block for the update data*/
					for(m = 0; m < TRDP_MINI_NBK_SIZES; m++){
						if(blockSize[m] >=  (dataSize-sizeof(TRDP_MINI_PD_HEAD_T))){
							pdInfo[i].dataSize = dataSize-sizeof(TRDP_MINI_PD_HEAD_T);
							/*find one block class can hold the data*/
							switch(blockSize[m]){
#if TRDP_MINI_BLKCNT_16B > 0
							case 16:
								for(b=0; b<TRDP_MINI_BLKCNT_16B; b++){
									if(gMem.mb16B[b].isValid == 0){
										gMem.mb16B[b].isValid = 1;
										memcpy(gMem.mb16B[b].data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)dataSize-sizeof(TRDP_MINI_PD_HEAD_T));
										pdInfo[i].pMemory = (void *)&gMem.mb16B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_32B > 0
							case 32:
								for(b=0; b<TRDP_MINI_BLKCNT_32B; b++){
									if(gMem.mb32B[b].isValid == 0){
										gMem.mb32B[b].isValid = 1;
										memcpy(gMem.mb32B[b].data,pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)dataSize-sizeof(TRDP_MINI_PD_HEAD_T));
										pdInfo[i].pMemory = (void *)&gMem.mb32B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_64B > 0
							case 64:
								for(b=0; b<TRDP_MINI_BLKCNT_64B; b++){
									if(gMem.mb64B[b].isValid == 0){
										gMem.mb64B[b].isValid = 1;
										memcpy(gMem.mb64B[b].data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)dataSize-sizeof(TRDP_MINI_PD_HEAD_T));
										pdInfo[i].pMemory = (void *)&gMem.mb64B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_128B > 0
							case 128:
								for(b=0; b<TRDP_MINI_BLKCNT_128B; b++){
									if(gMem.mb128B[b].isValid == 0){
										gMem.mb128B[b].isValid = 1;
										memcpy(gMem.mb128B[b].data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)dataSize-sizeof(TRDP_MINI_PD_HEAD_T));
										pdInfo[i].pMemory = (void *)&gMem.mb128B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_256B > 0
							case 256:
								for(b=0; b<TRDP_MINI_BLKCNT_256B; b++){
									if(gMem.mb256B[b].isValid == 0){
										gMem.mb256B[b].isValid = 1;
										memcpy(gMem.mb256B[b].data,pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)dataSize-sizeof(TRDP_MINI_PD_HEAD_T));
										pdInfo[i].pMemory = (void *)&gMem.mb256B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_512B > 0
							case 512:
								for(b=0; b<TRDP_MINI_BLKCNT_512B; b++){
									if(gMem.mb512B[b].isValid == 0){
										gMem.mb512B[b].isValid = 1;
										memcpy(gMem.mb512B[b].data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)dataSize-sizeof(TRDP_MINI_PD_HEAD_T));
										pdInfo[i].pMemory = (void *)&gMem.mb512B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_1024B > 0
							case 1024:
								for(b=0; b<TRDP_MINI_BLKCNT_1024B; b++){
									if(gMem.mb1024B[b].isValid == 0){
										gMem.mb1024B[b].isValid = 1;
										memcpy(gMem.mb1024B[b].data,pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)dataSize-sizeof(TRDP_MINI_PD_HEAD_T));
										pdInfo[i].pMemory = (void *)&gMem.mb1024B[b];
										break;
									}
								}
								break;
#endif
#if TRDP_MINI_BLKCNT_1348B > 0
							case 1348:
								for(b=0; b<TRDP_MINI_BLKCNT_1348B; b++){
									if(gMem.mb1348B[b].isValid == 0){
										gMem.mb1348B[b].isValid = 1;
										memcpy(gMem.mb1348B[b].data, pData+sizeof(TRDP_MINI_PD_HEAD_T), (int)dataSize-sizeof(TRDP_MINI_PD_HEAD_T));
										pdInfo[i].pMemory = (void *)&gMem.mb1348B[b];
										break;
									}
								}
								break;
#endif
							default:
								break;
							}
							if(pdInfo[i].pMemory != NULL){
								pdInfo[i].blockSize = blockSize[m];
								//break out if we find one
								break;
							}
						}
					}

					if(pdInfo[i].pUserCbFunc != NULL){
						pdInfo[i].pUserCbFunc(arg, pdInfo[i].comId, pData+sizeof(TRDP_MINI_PD_HEAD_T), dataSize-sizeof(TRDP_MINI_PD_HEAD_T), pRecvIp, recvPort, TRDP_MINI_NO_ERR);
					}
					break;
				}
			}
		}
	}
}

static void receive_md_callBack(void *arg, INT8U *pData, INT32U dataSize, INT8U *pRecvIp, INT16U recvPort)
{
	int i = 0;
	TRDP_MINI_MD_HEADER_T *pHeader = (TRDP_MINI_MD_HEADER_T *)pData;

	if(dataSize >= sizeof(TRDP_MINI_MD_HEADER_T)){
		if(sIsBigEndian != TRDP_MINI_USE_BIG_ENDIAN){
			//revert data in header
			pHeader->sequenceCounter = trdp_mini_until_RvINT32U(pHeader->sequenceCounter);
			pHeader->protocolVersion = trdp_mini_until_RvINT16U(pHeader->protocolVersion);
			pHeader->msgType = trdp_mini_until_RvINT16U(pHeader->msgType);
			pHeader->comId = trdp_mini_until_RvINT32U(pHeader->comId);
			pHeader->etbTopoCnt = trdp_mini_until_RvINT32U(pHeader->etbTopoCnt);
			pHeader->localTopoCnt = trdp_mini_until_RvINT32U(pHeader->localTopoCnt);
			pHeader->datasetLength = trdp_mini_until_RvINT32U(pHeader->datasetLength);
			pHeader->replyStatus = trdp_mini_until_RvINT32U(pHeader->replyStatus);
			pHeader->replyTimeout = trdp_mini_until_RvINT32U(pHeader->replyTimeout);
			pHeader->frameCheckSum = trdp_mini_until_RvINT32U(pHeader->frameCheckSum);
		}

		if(pHeader->msgType == TRDP_MINI_MSG_MN){
			 /**< 'Mn' MD Notification (Request without reply)    */
			for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
				if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (mdInfo[i].comId == pHeader->comId)){
					if((memcmp(mdInfo[i].sessionId, pHeader->sessionID, sizeof(mdInfo[i].sessionId)) == 0)){
						break;
					}else{
						memcpy(mdInfo[i].sessionId,  pHeader->sessionID, sizeof(mdInfo[i].sessionId));
					}
					//find listener to handle this notification
					mdInfo[i].pUserCbFunc(arg, pHeader->comId, MD_DO_NOTHING, pData+sizeof(TRDP_MINI_MD_HEADER_T), dataSize-sizeof(TRDP_MINI_MD_HEADER_T),
										 pHeader->localTopoCnt, pHeader->sessionID, pHeader->sourceURI, pHeader->destinationURI, pHeader->sequenceCounter,
										  pRecvIp, recvPort, TRDP_MINI_NO_ERR);
                    if((mdInfo[i].flagBits & FLAGS_MODE) == 0){
                        //we should release the control block first
                        if(mdInfo[i].pMemory != NULL){
                            //make the memory block invalid
                            *((INT32U *)mdInfo[i].pMemory) = 0;
                        }
                        //release the pdInfo
                        memset(&mdInfo[i], 0, sizeof(mdInfo[i]));
                    }
					break;
				}
			}
		}else if(pHeader->msgType == TRDP_MINI_MSG_MR){
			/**< 'Mr' MD Request with reply                      */
			for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
				if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (mdInfo[i].comId == pHeader->comId)){

					if((memcmp(mdInfo[i].sessionId, pHeader->sessionID, sizeof(mdInfo[i].sessionId)) == 0)){
						break;
					}else{
						memcpy(mdInfo[i].sessionId,  pHeader->sessionID, sizeof(mdInfo[i].sessionId));
					}

					/*
					if((mdInfo[i].flagBits & FLAGS_ENABLE) > 0){
					printf("request mdInfo[%d].sessionId = %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",i, mdInfo[i].sessionId[0],mdInfo[i].sessionId[1],mdInfo[i].sessionId[2],mdInfo[i].sessionId[3],
							mdInfo[i].sessionId[4],mdInfo[i].sessionId[5],mdInfo[i].sessionId[6],mdInfo[i].sessionId[7],
							mdInfo[i].sessionId[8],mdInfo[i].sessionId[9],mdInfo[i].sessionId[10],mdInfo[i].sessionId[11],
							mdInfo[i].sessionId[12],mdInfo[i].sessionId[13],mdInfo[i].sessionId[14],mdInfo[i].sessionId[15]);


					printf("\n\npHeader->sessionID = %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",pHeader->sessionID[0],pHeader->sessionID[1],pHeader->sessionID[2],pHeader->sessionID[3],
							pHeader->sessionID[4],pHeader->sessionID[5],pHeader->sessionID[6],pHeader->sessionID[7],
							pHeader->sessionID[8],pHeader->sessionID[9],pHeader->sessionID[10],pHeader->sessionID[11],
							pHeader->sessionID[12],pHeader->sessionID[13],pHeader->sessionID[14],pHeader->sessionID[15]);
					}
					*/

					mdInfo[i].pUserCbFunc(arg, pHeader->comId, MD_NEED_REPLY, pData+sizeof(TRDP_MINI_MD_HEADER_T), dataSize-sizeof(TRDP_MINI_MD_HEADER_T),
										 pHeader->localTopoCnt, pHeader->sessionID, pHeader->sourceURI, pHeader->destinationURI, pHeader->sequenceCounter,
										 pRecvIp, recvPort, TRDP_MINI_NO_ERR);
                    if((mdInfo[i].flagBits & FLAGS_MODE) == 0){
                        //we should release the control block first
                        if(mdInfo[i].pMemory != NULL){
                            //make the memory block invalid
                            *((INT32U *)mdInfo[i].pMemory) = 0;
                        }
                        //release the pdInfo
                        memset(&mdInfo[i], 0, sizeof(mdInfo[i]));
                    }
					break;
				}
			}
		}else if(pHeader->msgType == TRDP_MINI_MSG_MP){
			/**< 'Mp' MD Reply without confirmation              */
			for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
				if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (memcmp(mdInfo[i].sessionId, pHeader->sessionID, sizeof(mdInfo[i].sessionId)) == 0)){
					if(pHeader->replyStatus == 0){
						mdInfo[i].pUserCbFunc(arg, pHeader->comId, MD_DO_NOTHING, pData+sizeof(TRDP_MINI_MD_HEADER_T), dataSize-sizeof(TRDP_MINI_MD_HEADER_T),
											 pHeader->localTopoCnt, pHeader->sessionID, pHeader->sourceURI, pHeader->destinationURI, pHeader->sequenceCounter,
											 pRecvIp, recvPort, TRDP_MINI_NO_ERR);
					}else if(pHeader->replyStatus < 0){
						mdInfo[i].pUserCbFunc(arg, pHeader->comId, MD_DO_NOTHING, pData+sizeof(TRDP_MINI_MD_HEADER_T), dataSize-sizeof(TRDP_MINI_MD_HEADER_T),
											 pHeader->localTopoCnt, pHeader->sessionID, pHeader->sourceURI, pHeader->destinationURI, pHeader->sequenceCounter,
											 pRecvIp, recvPort, TRDP_MINI_UNKNOWN_ERR);
					}

					if((mdInfo[i].flagBits & FLAGS_MODE) == 0){
                        //we should release the control block first
                        if(mdInfo[i].pMemory != NULL){
                            //make the memory block invalid
                            *((INT32U *)mdInfo[i].pMemory) = 0;
                        }
                        //release the pdInfo
                        memset(&mdInfo[i], 0, sizeof(mdInfo[i]));
                    }
					//break;
				}
			}
		}else if(pHeader->msgType == TRDP_MINI_MSG_MQ){
			/**< 'Mq' MD Reply with confirmation                 */
			for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
				if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) &&(memcmp(mdInfo[i].sessionId, pHeader->sessionID, sizeof(mdInfo[i].sessionId)) == 0)){
					if(pHeader->replyStatus == 0){
						mdInfo[i].pUserCbFunc(arg, pHeader->comId, MD_NEED_CONFIRM, pData+sizeof(TRDP_MINI_MD_HEADER_T), dataSize-sizeof(TRDP_MINI_MD_HEADER_T),
											 pHeader->localTopoCnt, pHeader->sessionID, pHeader->sourceURI, pHeader->destinationURI, pHeader->sequenceCounter,
											 pRecvIp, recvPort,TRDP_MINI_NO_ERR);
					}else if(pHeader->replyStatus < 0){
						mdInfo[i].pUserCbFunc(arg, pHeader->comId, MD_NEED_CONFIRM, pData+sizeof(TRDP_MINI_MD_HEADER_T), dataSize-sizeof(TRDP_MINI_MD_HEADER_T),
											 pHeader->localTopoCnt, pHeader->sessionID, pHeader->sourceURI, pHeader->destinationURI, pHeader->sequenceCounter,
											 pRecvIp, recvPort, TRDP_MINI_UNKNOWN_ERR);
					}
					if((mdInfo[i].flagBits & FLAGS_MODE) == 0){
                        //we should release the control block first
                        if(mdInfo[i].pMemory != NULL){
                            //make the memory block invalid
                            *((INT32U *)mdInfo[i].pMemory) = 0;
                        }
                        //release the pdInfo
                        memset(&mdInfo[i], 0, sizeof(mdInfo[i]));
                    }
					//break;
				}
			}
		}else if(pHeader->msgType == TRDP_MINI_MSG_MC){
			/**< 'Mc' MD Confirm                                 */
			for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
				if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (memcmp(mdInfo[i].sessionId, pHeader->sessionID, sizeof(mdInfo[i].sessionId)) == 0)){
					mdInfo[i].pUserCbFunc(arg, pHeader->comId, MD_DO_NOTHING, pData+sizeof(TRDP_MINI_MD_HEADER_T), dataSize-sizeof(TRDP_MINI_MD_HEADER_T),
										 pHeader->localTopoCnt, pHeader->sessionID, pHeader->sourceURI, pHeader->destinationURI, pHeader->sequenceCounter,
										 pRecvIp, recvPort, TRDP_MINI_NO_ERR);
                    if((mdInfo[i].flagBits & FLAGS_MODE) == 0){
                        //we should release the control block first
                        if(mdInfo[i].pMemory != NULL){
                            //make the memory block invalid
                            *((INT32U *)mdInfo[i].pMemory) = 0;
                        }
                        //release the pdInfo
                        memset(&mdInfo[i], 0, sizeof(mdInfo[i]));
                    }
					//break;
				}
			}
		}else if(pHeader->msgType == TRDP_MINI_MSG_ME){
			/**< 'Me' MD Error                                   */
			for(i=0; i<TRDP_MINI_MD_CTRL_MAX_NUM; i++){
				if(((mdInfo[i].flagBits & FLAGS_ENABLE) > 0) && (memcmp(mdInfo[i].sessionId, pHeader->sessionID, sizeof(mdInfo[i].sessionId)) == 0)){
					mdInfo[i].pUserCbFunc(arg, pHeader->comId, MD_DO_NOTHING, NULL, 0,
										 pHeader->localTopoCnt, pHeader->sessionID, pHeader->sourceURI, pHeader->destinationURI, pHeader->sequenceCounter,
										 pRecvIp, recvPort, TRDP_MINI_UNKNOWN_ERR);
                    if((mdInfo[i].flagBits & FLAGS_MODE) == 0){
                        //we should release the control block first
                        if(mdInfo[i].pMemory != NULL){
                            //make the memory block invalid
                            *((INT32U *)mdInfo[i].pMemory) = 0;
                        }
                        //release the pdInfo
                        memset(&mdInfo[i], 0, sizeof(mdInfo[i]));
                    }
					//break;
				}
			}
		}
	}
}

/*------------------------------------------end of file----------------------------------------------------------*/


